package bma.common.langutil.core;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 数值工具类
 * 
 * @author 关中
 * @since 1.0 (imported from BMA.ESP Project)
 * 
 */
public class ValueUtil {

	static public String stringValue(String v, String def) {
		if (v == null)
			return def;
		return v;
	}

	static public String toString(Object v, String def) {
		if (v == null)
			return def;
		return v.toString();
	}

	static public byte byteValue(String v, byte def) {
		if (empty(v))
			return def;
		try {
			return Byte.parseByte(v);
		} catch (Exception e) {
			return def;
		}
	}

	static public byte toByte(Object v, byte def) {
		if (v == null)
			return def;
		if (v instanceof Number) {
			Number r = (Number) v;
			r.byteValue();
		}
		return byteValue(v.toString(), def);
	}

	static public char charValue(String v, char def) {
		if (empty(v))
			return def;
		try {
			return (char) Integer.parseInt(v);
		} catch (Exception e) {
			return def;
		}
	}

	static public char toChar(Object v, char def) {
		if (v == null)
			return def;
		if (v instanceof Character) {
			Character r = (Character) v;
			return r.charValue();
		}
		return charValue(v.toString(), def);
	}

	static public int intValue(String v, int def) {
		if (empty(v))
			return def;
		try {
			return Integer.parseInt(v);
		} catch (Exception e) {
			return def;
		}
	}

	static public int toInt(Object v, int def) {
		if (v == null)
			return def;
		if (v instanceof Number) {
			Number r = (Number) v;
			return r.intValue();
		}
		return intValue(v.toString(), def);
	}

	static public long longValue(String v, long def) {
		if (empty(v))
			return def;
		try {
			return Long.parseLong(v);
		} catch (Exception e) {
			return def;
		}
	}

	static public long toLong(Object v, long def) {
		if (v == null) {
			return def;
		}
		if (v instanceof Number) {
			Number r = (Number) v;
			return r.longValue();
		}
		return longValue(v.toString(), def);
	}

	static public boolean booleanValue(String v, boolean def) {
		if (empty(v))
			return def;

		if (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes")) {
			return true;
		} else if (v.equalsIgnoreCase("false") || v.equalsIgnoreCase("no")) {
			return false;
		} else {
			return def;
		}
	}

	static public boolean toBoolean(Object v, boolean def) {
		if (v == null) {
			return def;
		}
		if (v instanceof Boolean) {
			Boolean r = (Boolean) v;
			return r.booleanValue();
		}
		return booleanValue(v.toString(), def);
	}

	static public float floatValue(String v, float def) {
		if (empty(v))
			return def;
		try {
			return Float.parseFloat(v);
		} catch (Exception e) {
			return def;
		}
	}

	static public float toFloat(Object v, float def) {
		if (v == null)
			return def;
		if (v instanceof Number) {
			Number r = (Number) v;
			return r.floatValue();
		}
		return floatValue(v.toString(), def);
	}

	static public double doubleValue(String v, double def) {
		if (empty(v))
			return def;
		try {
			return Double.parseDouble(v);
		} catch (Exception e) {
			return def;
		}
	}

	static public double toDouble(Object v, double def) {
		if (v == null)
			return def;
		if (v instanceof Number) {
			Number r = (Number) v;
			return r.doubleValue();
		}
		return doubleValue(v.toString(), def);
	}

	static public Date dateValue(String v, String fm, Date def) {
		return DateTimeUtil.parse(v, fm, def);
	}

	/**
	 * yyyy-MM-dd
	 */
	static public Date dateValue(String v, Date def) {
		return DateTimeUtil.parseDate(v, def);
	}

	static public long dateValue(String v, long def) {
		return DateTimeUtil.parseDate(v, def);
	}

	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	static public Date datetimeValue(String v, Date def) {
		return DateTimeUtil.parseDateTime(v, def);
	}

	static public long datetimeValue(String v, long def) {
		return DateTimeUtil.parseDateTime(v, def);
	}

	static public Date parseDateTime(String v, Date def) {
		if (empty(v))
			return def;
		String[] dt = v.split(" ");
		String[] d = dt[0].split("-");
		String[] t = dt.length > 1 ? dt[1].split(":") : new String[0];

		Calendar defv = Calendar.getInstance();
		if (def != null) {
			defv.setTime(def);
		} else {
			defv.set(Calendar.HOUR_OF_DAY, 0);
			defv.set(Calendar.MINUTE, 0);
			defv.set(Calendar.SECOND, 0);
		}

		Calendar cal = Calendar.getInstance();
		int year = d.length - 3;
		int month = d.length - 2;
		int day = d.length - 1;

		cal.set(Calendar.YEAR,
				year < 0 ? defv.get(Calendar.YEAR) : intValue(d[year],
						defv.get(Calendar.YEAR)));
		cal.set(Calendar.MONTH, month < 0 ? defv.get(Calendar.MONTH)
				: intValue(d[month], defv.get(Calendar.MONTH) + 1) - 1);
		cal.set(Calendar.DAY_OF_MONTH,
				day < 0 ? defv.get(Calendar.DAY_OF_MONTH) : intValue(d[day],
						defv.get(Calendar.DAY_OF_MONTH)));

		int hour = 0;
		int minute = 1;
		int second = 2;

		cal.set(Calendar.HOUR_OF_DAY,
				hour >= t.length ? defv.get(Calendar.HOUR_OF_DAY) : intValue(
						t[hour], defv.get(Calendar.HOUR_OF_DAY)));
		cal.set(Calendar.MINUTE, minute >= t.length ? defv.get(Calendar.MINUTE)
				: intValue(t[minute], defv.get(Calendar.MINUTE)));
		cal.set(Calendar.SECOND, second >= t.length ? defv.get(Calendar.SECOND)
				: intValue(t[second], defv.get(Calendar.SECOND)));

		return cal.getTime();
	}

	/**
	 * Returns the value as a period.
	 * 
	 * <table>
	 * <tr>
	 * <td>s
	 * <td>seconds
	 * <tr>
	 * <td>m
	 * <td>minutes
	 * <tr>
	 * <td>h
	 * <td>hours
	 * <tr>
	 * <td>D
	 * <td>days
	 * <tr>
	 * <td>W
	 * <td>weeks
	 * </table>
	 * 
	 * @return the period in milliseconds, 0 if no period.
	 * 
	 *         period
	 */
	static public long periodValue(String value, long deflt) {
		return DateTimeUtil.parsePeriodValue(value, deflt);
	}

	static public long sizeValue(String value, long def) {
		try {
			return SizeUtil.convert(value, 1000, SizeUtil.B);
		} catch (Exception e) {
			return def;
		}
	}

	static public boolean empty(String e) {
		return e == null || e.length() == 0;
	}

	static public boolean notEmpty(String e) {
		return !empty(e);
	}

	public static Number decimalValue(String v, Number def) {

		if (v == null || v.length() == 0)
			return def;

		NumberFormat df = DecimalFormat.getInstance();
		try {
			return df.parse(v);
		} catch (Exception e) {
			return def;
		}
	}

	public static boolean isValueClass(Class cls) {
		if (ClassUtil.isMainClass(cls)) {
			return true;
		}

		if (cls == String.class) {
			return true;
		}

		if (cls == Class.class) {
			return true;
		}

		if (cls == Date.class) {
			return true;
		}

		if (cls.isEnum()) {
			return true;
		}

		return false;
	}

	public static Object toValue(Class to, Object v) throws Exception {
		if (v == null) {
			return getDefaultValue(to);
		}
		Class c = to.isPrimitive() ? ClassUtil.toMainClass(to) : to;
		if (v instanceof Number) {
			if (c == Boolean.class) {
				return ((Number) v).intValue() != 0;
			}
			if (c == Byte.class) {
				return ((Number) v).byteValue();
			}
			if (c == Character.class) {
				return (char) ((Number) v).intValue();
			}
			if (c == Short.class) {
				return ((Number) v).shortValue();
			}
			if (c == Integer.class) {
				return ((Number) v).intValue();
			}
			if (c == Long.class) {
				return ((Number) v).longValue();
			}
		}
		return strToValue(to, v.toString());
	}

	@SuppressWarnings("unchecked")
	public static Object strToValue(Class to, String v) throws Exception {
		if (to == String.class) {
			return v;
		}
		Class c = to.isPrimitive() ? ClassUtil.toMainClass(to) : to;
		if (ClassUtil.toMainClass(to) == Boolean.class) {
			return booleanValue(v, false);
		}
		if (c == Byte.class) {
			if (v.startsWith("0x")) {
				return Byte.valueOf(v.substring(2), 16);
			} else {
				return Byte.valueOf(v);
			}
		}
		if (c == Character.class) {
			Integer iv = null;
			if (v.startsWith("0x")) {
				iv = Integer.valueOf(v.substring(2), 16);
			} else {
				iv = Integer.valueOf(v);
			}
			return new Character((char) iv.intValue());
		}
		if (c == Short.class) {
			if (v.startsWith("0x")) {
				return Short.valueOf(v.substring(2), 16);
			} else {
				return Short.valueOf(v);
			}
		}
		if (c == Integer.class) {
			if (v.startsWith("0x")) {
				return Integer.valueOf(v.substring(2), 16);
			} else {
				return Integer.valueOf(v);
			}
		}
		if (c == Long.class) {
			if (v.startsWith("0x")) {
				return Long.valueOf(v.substring(2), 16);
			} else {
				return Long.valueOf(v);
			}
		}
		if (c == Float.class) {
			return Float.valueOf(v);
		}
		if (c == Double.class) {
			return Double.valueOf(v);
		}
		if (c == Class.class) {
			return ClassUtil.forName(v);
		}
		if (c == Date.class) {
			return parseDateTime(v, new Date());
		}
		if (c.isEnum()) {
			Class<? extends Enum> ecls = to.asSubclass(Enum.class);
			Enum valueOf = Enum.valueOf(ecls, v);
			return valueOf;
		}
		return null;
	}

	public static Object getDefaultValue(Class cls) {

		if (!cls.isPrimitive()) {
			return null;
		}

		if (cls == Boolean.TYPE) {
			return (boolean) false;
		}
		if (cls == Byte.TYPE) {
			return (byte) 0;
		}
		if (cls == Character.TYPE) {
			return (char) 0;
		}
		if (cls == Short.TYPE) {
			return (short) 0;
		}
		if (cls == Integer.TYPE) {
			return (int) 0;
		}
		if (cls == Long.TYPE) {
			return (long) 0;
		}
		if (cls == Float.TYPE) {
			return (float) 0;
		}
		if (cls == Double.TYPE) {
			return (double) 0;
		}
		return null;
	}
}
